/*	Copyright (c) 2010 MIEM (http://miem.edu.ru/)
 *
 *	Authors:
 *		* Andrey Shtykovskiy    ( ashty@itas.miem.edu.ru      )
 *		* Edward Klyshinsky     ( klyshinsky@itas.miem.edu.ru )
 *		* Sergey R. Tumkovsky   ( srt@itas.miem.edu.ru        )
 *
 *	This file is part of MOAN (morphology analysis) software.
 *
 *	MOAN is free software: you can redistribute it and/or modify it 
 *	under the terms of the GNU General Public License as published 
 *	by the Free Software Foundation, either version 3 of the License, 
 *	or (at your option) any later version.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *	Lesser General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License 
 *	along with MOAN. If not, see http://www.gnu.org/licenses/.
 */

#ifndef __BIT_RAKE_UNITTEST_HPP_GUARD__
#define __BIT_RAKE_UNITTEST_HPP_GUARD__

#include <stdint.h>

#include "..\..\thirdparty\gtest\gtest.h"

#include "..\..\src\moan\bit_rake.hpp"

class bit_rake_basic_test : public ::testing::Test {

protected:
	typedef moan::bit_rake<uint64_t> container_type;

	virtual void SetUp() {
		br = new container_type();
	}

	virtual void TearDown() {
		delete br;
		br = NULL;
	}

	container_type *br;
};

TEST_F( bit_rake_basic_test, on_create ) {
	ASSERT_EQ( 0, br->value() );
	ASSERT_EQ( 63, br->cap() );
}

TEST_F( bit_rake_basic_test, from_value ) {
	br->from_value(100);
	ASSERT_EQ( 100, br->value() );
}

TEST_F( bit_rake_basic_test, flip ) {
	br->flip(0);
	ASSERT_EQ( 1, br->value() );

	br->flip(0);
	ASSERT_EQ( 0, br->value() );

	br->flip(1);
	ASSERT_EQ( 2, br->value() );

	br->flip(1); // reset

	br->flip(63); 
	ASSERT_EQ( INT64_MAX, br->value() - 1 );
}

TEST_F( bit_rake_basic_test, set_drop ) {
	br->set(0);
	ASSERT_EQ( 1, br->value() );

	br->set(0);
	ASSERT_EQ( 1, br->value() );

	br->drop(0);
	ASSERT_EQ( 0, br->value() );

	br->set(63);
	ASSERT_EQ( INT64_MAX, br->value() - 1 );

	br->drop(63);
	ASSERT_EQ( 0, br->value() );
}

TEST_F( bit_rake_basic_test, extract ) {
	br->set(10);
	ASSERT_EQ( 1024, br->extract(10) );
	ASSERT_EQ( 1024, br->value() );

	br->set(11);
	ASSERT_EQ( 1024, br->extract(10) );
	ASSERT_EQ( 3072, br->value() );
}

TEST_F( bit_rake_basic_test, extract_and_accumulate ) {
	br->set(0);
	br->set(1);

	container_type::value_type v = 0;

	v |= br->extract(0);
	v |= br->extract(1);

	ASSERT_EQ( 3, v );
	ASSERT_EQ( v, br->value() );
}


TEST_F( bit_rake_basic_test, extract_range ) {
	br->set(10);
	ASSERT_EQ( 1024, br->extract(10, 15) );
	ASSERT_EQ( 1024, br->value() );

	br->set(11);
	ASSERT_EQ( 3072, br->extract(10, 15) );
	ASSERT_EQ( 3072, br->value() );

	br->set(9);
	ASSERT_EQ( 3072, br->extract(10, 15) );
	ASSERT_EQ( 3584, br->value() );

}

#endif /* __BIT_RAKE_UNITTEST_HPP_GUARD__ */